Skip to content

Apply features from the commandline first #3960

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 2, 2021
Merged

Apply features from the commandline first #3960

merged 6 commits into from
Jul 2, 2021

Conversation

kripken
Copy link
Member

@kripken kripken commented Jul 1, 2021

As suggested in

#3955 (comment)

This applies commandline features first. If the features section is present, and
disallows some of them, then we warn. Otherwise, the features can combine
(for example, a wasm may enable feature X because it has to use it, and a user
can simply add the flag for feature Y if they want the optimizer to try to use it;
both flags will then be enabled).

This is important because in some cases we need to know the features before
parsing the wasm, in the case that the wasm does not use the features section.
In particular, non-nullable GC locals have an effect during parsing. (Typed
function references also does, but we found a way to apply its effect all the time,
that is, always use the refined type, and that happened to not break the case
where the feature is disabled - but such a workaround is not possible with
non-nullable locals.)

To make this less error-prone, add a FeatureSet input as a parameter to
WasmBinaryBuilder. That is, when building a module, we must give it the
features to use while doing so.

This will unblock #3955 . That PR will also add a test for the actual usage
of a feature during loading (the test can only be added there, after that PR
unbreaks things).

@kripken kripken requested a review from tlively July 1, 2021 21:33
Copy link
Member

@tlively tlively left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I think this is a good change to make. I do also think it would be good to pre-parse the target features section, too. Otherwise, once we depend on features during parsing, it won't be possible to parse correctly when a feature is in the target features section but not on the command line.

@@ -3974,7 +3974,8 @@ BinaryenModuleRef BinaryenModuleRead(char* input, size_t inputSize) {
buffer.resize(inputSize);
std::copy_n(input, inputSize, buffer.begin());
try {
WasmBinaryBuilder parser(*wasm, buffer);
// TODO: allow providing features in the C API
WasmBinaryBuilder parser(*wasm, FeatureSet::MVP, buffer);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
WasmBinaryBuilder parser(*wasm, FeatureSet::MVP, buffer);
WasmBinaryBuilder parser(*wasm, FeatureSet::All, buffer);

This is closer to the previous behavior. I would be surprised if it weren't also required by our tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow you. Wouldn't this only be needed if we used to enable all the features in this code path? I don't see that. This should have no effect, that is, it sets the features to MVP, which is the default of a module anyhow.

But maybe I'm missing something... the tests on CI all failed due to lint, which is fixed now, so we can see what happens. Locally though they seem to pass for me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, never mind about the tests. I was thinking that the feature set here would control what feature would be able to be parsed, but that's not right. Why does this code have to change at all? FeatureSet::MVP is already the default feature set on a Module.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line changes only because I changed the API. I made the wasm binary builder class take a FeatureSet as a parameter. That feels nicer than the user setting the features on the module before in a separate operation. I could make this new parameter to the constructor default to MVP, and then this line could not change?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this capability isn't used anywhere except to set the features to MVP, which they already are, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RoundTrip for example does apply the known correct features:

-    WasmBinaryBuilder parser(*module, input);
+    WasmBinaryBuilder parser(*module, features, input);

(And in wasm-io we set the features as well, although there we set them from the module, because that is all it has - a larger refactoring might also add an API there to get the features.)

@@ -362,7 +362,8 @@ SExpressionWasmBuilder::SExpressionWasmBuilder(Module& wasm,
stringToBinary(str, size, data);
}
}
WasmBinaryBuilder binaryBuilder(wasm, data);
// TODO: support applying features here
WasmBinaryBuilder binaryBuilder(wasm, FeatureSet::MVP, data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
WasmBinaryBuilder binaryBuilder(wasm, FeatureSet::MVP, data);
WasmBinaryBuilder binaryBuilder(wasm, FeatureSet::All, data);

We should leave disallowed features to be caught by validation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand you here either, sorry... How would enabling all features get us more validation in the text parser? (the text parser has no feature section parsing, but even if it did..?)

(tests passed)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking that we would want to be able to parse all features by default, but the feature set passed here won't actually control what features can be parsed, so I was confused. Disregard this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, why does this need to change to apply a new feature set? Can't it just keep the default one that wasm already had?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same issue as above, I think)

@kripken
Copy link
Member Author

kripken commented Jul 2, 2021

Agreed about pre-parsing the feature section, I think we will need that eventually (when we have a case that parsing is affected by a feature, and the feature is in the feature section - which might happen if someone starts to use the features section with gc-nn-locals...).

Copy link
Member

@tlively tlively left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Thanks for your patience!

Oh, actually #3960 (comment)

@kripken kripken merged commit d2347ff into main Jul 2, 2021
@kripken kripken deleted the feat branch July 2, 2021 15:29
kripken added a commit that referenced this pull request Jul 13, 2021
The features section is additive since #3960. For the fuzzer to know which features
are used, it therefore needs to also scan the features section. To do this,
run --print-features to get the total features used from both flags + the
features section.

A result of this is that we now have a list of enabled features instead of
"enable all, then disable". This is actually clearer I think, but it does require
inverting the logic in some places.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants